package com.zhj.helloframework.mvc;

import com.zhj.helloframework.aop.AspectWeaver;
import com.zhj.helloframework.core.BeanContainer;
import com.zhj.helloframework.injection.DependencyInjector;
import com.zhj.helloframework.mvc.processer.RequestProcessor;
import com.zhj.helloframework.mvc.processer.impl.ControllerRequestProcessor;
import com.zhj.helloframework.mvc.processer.impl.JspRequestProcessor;
import com.zhj.helloframework.mvc.processer.impl.PreRequestProcessor;
import com.zhj.helloframework.mvc.processer.impl.StaticResourceRequestProcessor;
import lombok.extern.slf4j.Slf4j;


import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * @Author: zhj
 * @Description: 拦截所有http请求，并交给后续逻辑处理
 * @Date: 2021/10/12 19:00
 * @Version: 1.0
 */
// 指定该servlet的访问路径是/*，说明所有的http请求都会被servlet拦截下来并交给service进行处理
@WebServlet("/*")
@Slf4j
public class DispatcherServlet extends HttpServlet {

    // 指明MVC相关配置文件的位置
    private static final String HELLOFRAMEWORK_CONFIG_FILE = "config/helloframework-config.properties";
    // 存放该http请求需要经过的处理器
    private List<RequestProcessor> PROCESSOR = new ArrayList<>();

    // init()方法会在该Servlet第一次被创建时调用，会在该方法中进行aop和ioc的初始化
    @Override
    public void init() throws ServletException {
        // 1.初始化容器
        BeanContainer beanContainer = BeanContainer.getInstance();
        // 2.加载指定包下的bean，并进行实例化
        beanContainer.loadBeans(getHelloFrameworkScanPackages());
        // 3.进行aop增强和ioc注入
        new AspectWeaver().doAop();
        new DependencyInjector().doIoc();
        // 4.初始化请求处理器责任链
        PROCESSOR.add(new PreRequestProcessor());
        PROCESSOR.add(new StaticResourceRequestProcessor(getServletContext()));
        PROCESSOR.add(new JspRequestProcessor(getServletContext()));
        PROCESSOR.add(new ControllerRequestProcessor());
    }

    // 获取指定配置文件下的具体配置属性
    private String getHelloFrameworkScanPackages() {
        Properties properties = new Properties();
        // 读取并加载properties类型的配置文件
        InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(HELLOFRAMEWORK_CONFIG_FILE);
        try {
            properties.load(is);
        } catch (IOException e) {
            log.warn("The config/helloframework.properties can not load");
            e.printStackTrace();
        }
        // 根据key读取到要扫描的包路径
        String scanPackages  = properties.getProperty("helloframework.scan.packages");
        log.info("this is scanPackages: {}", scanPackages);
        return scanPackages;
    }

    // 每当有http请求时都会调用该方法
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        // 1.创建责任链对象实例
        RequestProcessorChain requestProcessorChain = new RequestProcessorChain(PROCESSOR.iterator(), req, res);
        // 2.通过责任链模式来依次调用请求处理器来对请求进行处理
        requestProcessorChain.doRequestProcessorChain();
        // 3.对处理结果进行渲染
        requestProcessorChain.doRender();
    }
}
